package oboe.controllers.jml.helpers.window;

import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.text.TextField;

import oboe.controllers.jml.JMLController;
import oboe.controllers.jml.helpers.JMLNode;

class JMLWindow extends JMLNode
{
public function new( key:String, val:Object, parent:JMLController )
{
	super( key, val, parent );
}

protected override function createDisplayObject(type:String):DisplayObject
{
	return new WindowView();
}
}
}

import flash.display.DisplayObject;
import flash.display.GradientType;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.filters.DropShadowFilter;
import flash.geom.Matrix;
import flash.geom.Rectangle;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;

import oboe.controllers.jml.events.JMLEvent;
import oboe.core.Controller;
import oboe.core.Oboe;
import oboe.math.Number2D;

class WindowView extends Sprite
{
private var dragData:DragData;

public var titleBarHeight:Int = 20;
public var titleBarColor1:Int = 0xE0E0E0;
public var titleBarColor2:Int = 0xA0A0A0;
public var windowFillColor:Int = 0x7F7F7F;
public var windowBorderColor:Int = 0xAFAFAF;
public var titleBarTextColor:Int = 0x0F0F0F;

private var minSize:Float2D;

public function WindowView()
{
super();
Object(this).addCallback( JMLEvent.JMLCOMPLETE, onComplete).once = true;

this.minSize = new Number2D(0,0);

this.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
this.dragData = new DragData();

// Flash bugfix for sprite to report correct width/height
this.graphics.beginFill(0, 1);
this.graphics.drawRect(0,0,1000,1000);
this.graphics.endFill();
}

public function requireMinSize( w:Int, h:Int ):Void
{
minSize.x = Math.max( minSize.x, w );
minSize.y = Math.max( minSize.y, h );
}

private function onMouseDown( e:MouseEvent ):Void
{
if( e.target == this && e.localY < this.titleBarHeight ) 
{
	this.dragData.startDrag( this, e );
}
}

private function onAddToStage():Void
{
this.x = this.stage.stageWidth/2 - this.width/2;
this.y = this.stage.stageHeight/2 - this.height/2;
}

private function onComplete( ):Void
{
if( !this.x && !this.y )
{
	Object(this).addCallback( Event.ADDED_TO_STAGE, onAddToStage );
}

this.requireMinSize( 100, this.titleBarHeight + this.resizeButtonSize );

this.redraw();

this.filters = [
	new DropShadowFilter(5, 45, 0, 0.5, 6, 6)
];
}

public function redraw():Void	
{
var width:Float = this.width;
var height:Float = this.height;
this.scaleX = this.scaleY = 1;
this.graphics.clear();

this.drawWindow( width, height );
}

include "_closebutton.as3";
include "_resizebutton.as3";

private function drawWindow( width:Float, height:Float ):Void
{
width = Math.max( width, this.minSize.x );
height = Math.max( height, this.minSize.y );

this.scrollRect = new Rectangle(0, 0, width, height);

this.graphics.clear();

this.graphics.lineStyle(2, this.windowBorderColor, 1);
this.graphics.beginFill( this.windowFillColor, 1);
this.graphics.drawRect(0, 0, width, height);
this.graphics.endFill();

// this.graphics.beginFill( this.titleBarColor, 1);
var box:Matrix = new Matrix();
box.createGradientBox( width, titleBarHeight, Math.PI/2 );
this.graphics.beginGradientFill( GradientType.LINEAR, [this.titleBarColor1, this.titleBarColor2], [1, 1], [0, 255], box );
this.graphics.drawRect(0, 0, width, titleBarHeight);
this.graphics.endFill();

adjustControl(
	width, height,
	this.showCloseButton, 
	this.closeButtonSprite, 
	this.addCloseButton,
	this.adjustCloseButton
);
adjustControl( 
	width, height,
	this.showResizeButton, 
	this.resizeButtonSprite, 
	this.addResizeButton,
	this.adjustResizeButton
);
}

private function adjustControl( width:Float, height:Float, flag:Bool, asset:DisplayObject, factory:Function, adjust:Function ):Void
{
if( flag )
{
	if( !asset ) asset = factory();
	adjust( width, height );
	
	if( asset.parent != this )
	{
	this.addChild( asset );
	}
}
else
{
	if( asset && asset.parent == this )
	{
	this.removeChild( asset );
	}
}
}

public var title(null, setTitle):String;
 	private function setTitle(t:String):Void
{
if( !titleAsset )
{
	titleAsset = new TextField();
	titleAsset.textColor = titleBarTextColor;
	titleAsset.autoSize = TextFieldAutoSize.LEFT;
	titleAsset.mouseEnabled = false;
	this.addChild( titleAsset );
}

titleAsset.text = t;
}

private var titleAsset:TextField;
}

class DragData
{
public var isDragging:Bool;
public var dragOffset:Float2D;
private var target:DisplayObject;
private var callback:Function;

public function DragData()
{
this.isDragging = false;
this.dragOffset = new Number2D(0,0);
}

public function startDrag( target:DisplayObject, e:MouseEvent, callback:Function=null ):Void
{
this.target = target as DisplayObject;
this.callback = callback;
if( !this.isDragging )
{
	Oboe.stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
}

this.dragOffset.set( e.stageX, e.stageY );
this.isDragging = true;
}

private function onMouseMove( e:MouseEvent ):Void
{
if( !this.isDragging || !e.buttonDown )
{
	Oboe.stage.removeEventListener( MouseEvent.MOUSE_MOVE, onMouseMove );
	this.isDragging = false;
	Oboe.stage.mouseChildren = true;
	return;
}

Oboe.stage.mouseChildren = false;

var deltaX:Float = e.stageX - this.dragOffset.x;
var deltaY:Float = e.stageY - this.dragOffset.y;
this.target.x += deltaX;
this.target.y += deltaY;
this.dragOffset.x = e.stageX;
this.dragOffset.y = e.stageY;
if( this.callback != null ) this.callback( this.target.x, this.target.y );
}